/**
 * PCM 音频处理器 (AudioWorklet)
 * 将浮点音频数据转换为 16-bit PCM 格式并进行 VAD
 * 版本: 2025-11-05 v11 (双模式支持)
 * 
 * 工作流程：
 * 1. 持续发送小块PCM数据（isSpeechSegment=false）
 *    -> 用于图片帧模式（AudioToPCMConverter），实时生成帧
 * 2. 同时进行智能整句检测
 *    -> 检测语音开始/结束，累积完整语句
 *    -> 发送完整语音段（isSpeechSegment=true）
 *    -> 用于视频流模式（aiChat_video.vue），生成完整视频
 */
class PCMProcessor extends AudioWorkletProcessor {
  constructor() {
    super()
    this.sampleRate = 16000 // 目标采样率
    
    // 🎯 智能整句检测模式
    this.VAD_THRESHOLD = 0.05            // VAD 能量阈值（调低以更敏感）
    this.SILENCE_DURATION_MS = 800       // 静音持续时间（判断句子结束）
    this.MIN_SPEECH_DURATION_MS = 300    // 最小语音时长（过滤噪音）
    this.MAX_SPEECH_DURATION_MS = 30000   // 最大语音时长（避免过长）
    
    this.buffer = []                     // 音频缓冲区
    this.isSpeaking = false              // 是否正在说话
    this.lastSpeechTime = 0              // 上次检测到语音的时间
    this.speechStartTime = 0             // 语音开始时间
    
    console.log(`🎙️ PCMProcessor initialized: sentence detection mode`)
    console.log(`   VAD: ${this.VAD_THRESHOLD}, silence: ${this.SILENCE_DURATION_MS}ms, min: ${this.MIN_SPEECH_DURATION_MS}ms`)
  }

  process(inputs, outputs, parameters) {
    const input = inputs[0]
    
    // 检查是否有输入数据
    if (!input || !input[0] || input[0].length === 0) {
      return true
    }
    
    const inputData = input[0]
    const now = Date.now()
    
    // 计算音频能量（用于 VAD）
    let energy = 0
    for (let i = 0; i < inputData.length; i++) {
      energy += inputData[i] * inputData[i]
    }
    energy = Math.sqrt(energy / inputData.length)
    
    // 转换为 PCM
    const pcmData = this.floatTo16BitPCM(inputData)
    
    // 🔄 持续发送小块PCM数据（用于图片帧模式）
    // 复制一份用于发送，原始数据用于累积
    const pcmDataCopy = pcmData.slice(0)
    this.port.postMessage({
      pcmData: pcmDataCopy,
      maxAmplitude: Math.sqrt(energy),
      sampleCount: inputData.length,
      isSpeechSegment: false  // 标记为小块，不是完整语句
    }, [pcmDataCopy])
    
    // 🎯 智能整句检测（用于累积完整语句）
    if (energy > this.VAD_THRESHOLD) {
      // 检测到语音
      if (!this.isSpeaking) {
        // 语音开始
        console.log('🎤 Speech started - accumulating sentence...')
        this.isSpeaking = true
        this.speechStartTime = now
        this.buffer = [] // 清空缓冲区，开始新的语句
      }
      
      this.lastSpeechTime = now
      this.buffer.push(pcmData)
      
      // 检查是否超过最大时长（强制发送）
      const speechDuration = now - this.speechStartTime
      if (speechDuration >= this.MAX_SPEECH_DURATION_MS) {
        console.log(`⏱️ Max speech duration reached (${speechDuration}ms), sending...`)
        this.flushBuffer(true)
      }
    } else {
      // 静音
      if (this.isSpeaking) {
        const silenceDuration = now - this.lastSpeechTime
        
        // 继续累积音频（包括短暂静音，保持连贯性）
        if (silenceDuration < this.SILENCE_DURATION_MS) {
          this.buffer.push(pcmData)
        } else {
          // 静音持续时间足够，判断语句结束
          const speechDuration = this.lastSpeechTime - this.speechStartTime
          
          if (speechDuration >= this.MIN_SPEECH_DURATION_MS) {
            console.log(`✅ Speech ended (duration: ${speechDuration}ms), sending complete sentence...`)
            this.flushBuffer(true)
          } else {
            console.log(`⚠️ Speech too short (${speechDuration}ms), discarding as noise`)
            this.buffer = []
          }
          
          this.isSpeaking = false
        }
      }
    }
    
    return true // 继续处理
  }
  
  /**
   * 发送缓冲的完整语音段
   * @param {boolean} isCompleteSentence - 是否为完整语句
   */
  flushBuffer(isCompleteSentence = false) {
    if (this.buffer.length === 0) {
      return
    }
    
    // 计算总字节数
    let totalBytes = 0
    for (let i = 0; i < this.buffer.length; i++) {
      totalBytes += this.buffer[i].byteLength
    }
    
    // 合并所有PCM数据
    const merged = new ArrayBuffer(totalBytes)
    const mergedView = new Uint8Array(merged)
    let offset = 0
    
    for (let i = 0; i < this.buffer.length; i++) {
      const chunk = new Uint8Array(this.buffer[i])
      mergedView.set(chunk, offset)
      offset += chunk.byteLength
    }
    
    // 计算时长
    const durationSec = (totalBytes / 2 / this.sampleRate).toFixed(2)
    
    // 发送合并后的完整语音段
    console.log(`📤 Sending complete sentence: ${totalBytes} bytes (${(totalBytes / 1024).toFixed(1)}KB, ${durationSec}s)`)
    this.port.postMessage({
      pcmData: merged,
      maxAmplitude: 1.0,
      sampleCount: totalBytes / 2,
      isSpeechSegment: isCompleteSentence  // 🎯 标记为完整语句
    }, [merged])
    
    // 清空缓冲区
    this.buffer = []
  }

  /**
   * 转换 Float32Array 到 16-bit PCM ArrayBuffer
   */
  floatTo16BitPCM(float32Array) {
    const buffer = new ArrayBuffer(float32Array.length * 2)
    const view = new DataView(buffer)
    
    // 🔊 音频增益：放大3倍（避免削波）
    // 如果数字人动作不够明显，可以提高到 4.0
    const gain = 3.0
    
    for (let i = 0; i < float32Array.length; i++) {
      // 应用增益并限制在 [-1, 1] 范围内
      const s = Math.max(-1, Math.min(1, float32Array[i] * gain))
      // 转换为 16-bit 整数
      const val = s < 0 ? s * 0x8000 : s * 0x7FFF
      view.setInt16(i * 2, val, true) // true = little-endian
    }
    
    return buffer
  }
}

// 注册处理器
registerProcessor('pcm-processor', PCMProcessor)